#pragma once

#include "IObserver.h"

template <class T>
class Subject
{
public:
	virtual ~Subject()
	{
		for(std::vector<IObserver<T>*>::iterator i=m_observers.begin(); i!=m_observers.end(); ++i)
            (*i)->NotifyOfDeath( this );
	}
	void NotifyAll(T &e)
	{
		for(std::vector<IObserver<T>*>::iterator i=m_observers.begin(); i!=m_observers.end(); ++i)
            (*i)->Notify(e, this);
    }
    void addObserver(IObserver<T> *o)
	{
		m_observers.push_back(o);
		o->Notify(m_object, this);
	}
    void removeObserver(IObserver<T> *o)
	{
		for (std::vector<IObserver<T>*>::iterator it = m_observers.begin(); it != m_observers.end(); ++it)
		{
			if (*it == o)
			{
				m_observers.erase(it);
				break;
			}
		}
	}
	T& getObject()
	{
		return m_object;
	}
	std::vector<IObserver<T>*>& getObservers()
	{
		return m_observers;
	};
	operator T()
	{
		return m_object;
	};
	T& operator= (const T& o)
	{
		m_object = o;
		NotifyAll(m_object);
		return m_object;
	};
	T& operator+= (const T& o)
	{
		m_object += o;
		NotifyAll(m_object);
		return m_object;
	};
	T& operator-= (const T& o)
	{
		m_object -= o;
		NotifyAll(m_object);
		return m_object;
	};
	T operator+ (const T& o)
	{
		return m_object + o;
	}
	T operator- (const T& o)
	{
		return m_object - o;
	}
	T& operator*= (const T& o)
	{
		m_object *= o;
		NotifyAll(m_object);
		return m_object;
	};
	T& operator/= (const T& o)
	{
		m_object /= o;
		NotifyAll(m_object);
		return m_object;
	};
	T operator* (const T& o)
	{
		return m_object * o;
	}
	T operator/ (const T& o)
	{
		return m_object / o;
	}
private:
	T m_object;
	std::vector<IObserver<T>*> m_observers;
};